package com.wjh.www.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;


/**
 * @author 26913
 * 处理前端参数的工具类，完成参数类型自动转化
 */
public class BeanUtil {
    private static final Logger logger = LoggerUtil.getLogger();

    /**
     * 封装前端传递过来的大量参数
     *
     * @param clazz 对应po类的class
     * @param map   req.getParameterMap()
     * @return 返回一个po类对象
     */
    public static <T> T packParams(Class<?> clazz, Map<String, String[]> map) {
        List<Field> fields;
        Object obj;
        try {
            //构建对象
            obj = clazz.newInstance();
            fields = ReflectUtil.getFields(obj);
        } catch (InstantiationException | IllegalAccessException e) {
            logger.severe("无法实例化传入的类（clazz）：" + clazz.getName());
            e.printStackTrace();
            throw new RuntimeException("无法实例化传入的类（clazz）：" + clazz.getName());
        }

        for (Field field : fields) {
            //由于前端传过来的值都是String类型，所有获取每个属性的String类型的构造器来实例化成po类属性对应的类型
            Constructor<?> constructor;
            try {
                constructor = field.getType().getConstructor(String.class);
            } catch (Exception e) {
                logger.severe("该变量没有String类型参数的构造器" + field.getName());
                throw new RuntimeException("该变量没有String类型参数的构造器" + field.getName());
            }

            //利用反射构造po类属性
            String[] paramString = map.get(field.getName());
            if (paramString != null && paramString[0] != null) {
                Object value;
                try {
                    //获取属性名
                    String filedName = field.getName();
                    //根据属性名获取setXxx方法
                    String methodName = "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
                    //通过methodName（String类型）获取method（Method类型）
                    Method method = clazz.getMethod(methodName, field.getType());

                    try {
                        //通过po类中属性的String类型构造器构造属性
                        value = constructor.newInstance(paramString[0]);
                    } catch (Exception e) {
                        value = null;
                    }
                    //反射，调用属性对应的setXxx方法
                    method.invoke(obj, value);
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    logger.severe("无法初始化该属性: " + field.getName() + " 属性值：" + paramString[0]);
                    e.printStackTrace();
                    throw new RuntimeException("无法初始化该属性: " + field.getName() + " 属性值：" + paramString[0]);
                }
            }
        }
        return (T) obj;
    }
}
